package logers

import (
	"context"
	"gitee.com/sourcandy/filter/ginv"
	"github.com/google/uuid"
	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"
	"gopkg.in/natefinch/lumberjack.v2"
	"os"
	"time"
)

type Log interface {
	Run(e *zerolog.Event, level zerolog.Level, msg string)
	Reader() error
}

type LogHook struct {
	RequestId string `json:"request_id"`
}

type SeverityHook struct {
	*LogHook
	zerolog.Logger
	writePath string `json:"write_path"`
	logExt    string `json:"log_ext"`
	Error     error
}

func WithLogExt(ext string) HookOption {
	return func(opt *SeverityHook) {
		opt.logExt = ext
	}
}

func WithWritePath(path string) HookOption {
	return func(opt *SeverityHook) {
		opt.writePath = path
	}
}

type HookOption func(s *SeverityHook)

func NewLog(options ...HookOption) *SeverityHook {
	uid, _ := uuid.NewUUID()
	hook := &SeverityHook{
		logExt: "log",
		LogHook: &LogHook{
			RequestId: uid.String(),
		},
	}
	for _, opt := range options {
		opt(hook)
	}
	return hook
}

func (h *LogHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
	ctx := e.GetCtx()
	ctxs := ginv.GetCtx(ctx)
	if _, ok := ctxs.Value(ginv.RequestId).(string); !ok {
		ctxs = context.WithValue(ctxs, ginv.RequestId, uuid.New().String())
	}
	e.Str(ginv.RequestId, ctxs.Value(ginv.RequestId).(string))
}

func (h *SeverityHook) Reader() *SeverityHook {
	name := time.Now().Format("2006-01-02")
	logRotate := &lumberjack.Logger{
		Filename:   h.writePath + "/" + name + "." + h.logExt, // 文件位置
		MaxSize:    10,                                        // megabytes，M 为单位，达到这个设置数后就进行日志切割
		MaxBackups: 3,                                         // 保留旧文件最大份数
		MaxAge:     30,                                        //days ， 旧文件最大保存天数
		Compress:   true,                                      // disabled by default，是否压缩日志归档，默认不压缩
	}
	consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.StampMilli}
	multi := zerolog.MultiLevelWriter(consoleWriter, logRotate)
	log.Logger = log.Output(multi).Hook(h.LogHook)
	h.Logger = log.Logger
	return h
}
